<!DOCTYPE HTML>
<html lang="zh-Hans" class="sidebar-visible no-js light">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>Deref AsRef Borrow Cow 释义 - Rust 优秀博文</title>


        <!-- Custom HTML head -->
        
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

        <link rel="icon" href="../../favicon.svg">
        <link rel="shortcut icon" href="../../favicon.png">
        <link rel="stylesheet" href="../../css/variables.css">
        <link rel="stylesheet" href="../../css/general.css">
        <link rel="stylesheet" href="../../css/chrome.css">
        <link rel="stylesheet" href="../../css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="../../FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="../../fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="../../highlight.css">
        <link rel="stylesheet" href="../../tomorrow-night.css">
        <link rel="stylesheet" href="../../ayu-highlight.css">

        <!-- Custom theme stylesheets -->

    </head>
    <body>
        <!-- Provide site root to javascript -->
        <script type="text/javascript">
            var path_to_root = "../../";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script type="text/javascript">
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('no-js')
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add('js');
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var html = document.querySelector('html');
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">1.</strong> 类型系统</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../01_类型系统/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow.html"><strong aria-hidden="true">1.1.</strong> Rust Concept Clarification Deref vs AsRef vs Borrow vs Cow</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow/Deref_AsRef_Borrow_Cow释义.html" class="active"><strong aria-hidden="true">1.2.</strong> Deref AsRef Borrow Cow 释义</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然/Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然.html"><strong aria-hidden="true">1.3.</strong> Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust的Cow类型有什么用？详解Cow及其用途/Rust的Cow类型有什么用？详解Cow及其用途.html"><strong aria-hidden="true">1.4.</strong> Rust的Cow类型有什么用？详解Cow及其用途</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/判别Fn、FnMut、FnOnce的标准/判别Fn、FnMut、FnOnce的标准.html"><strong aria-hidden="true">1.5.</strong> 判别Fn、FnMut、FnOnce的标准</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/一行代码告诉你内部可变性的真相(UnsafeCell)/一行代码告诉你内部可变性的真相(UnsafeCell).html"><strong aria-hidden="true">1.6.</strong> 一行代码告诉你内部可变性的真相(UnsafeCell)</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Tour_of_Rust's_Standard_Library_Traits/Tour_of_Rust's_Standard_Library_Traits.html"><strong aria-hidden="true">1.7.</strong> Tour of Rust's Standard Library Traits</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/逆变、协变与子类型，以及Rust/逆变、协变与子类型，以及Rust.html"><strong aria-hidden="true">1.8.</strong> 逆变、协变与子类型，以及Rust</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust自引用结构、Pin与Unpin/Rust自引用结构、Pin与Unpin.html"><strong aria-hidden="true">1.9.</strong> Rust自引用结构、Pin与Unpin</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/为什么Rust需要Pin,Unpin/为什么Rust需要Pin,Unpin.html"><strong aria-hidden="true">1.10.</strong> 译：为什么 Rust 需要 Pin, Unpin ？</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/定海神针Pin和Unpin/定海神针Pin和Unpin.html"><strong aria-hidden="true">1.11.</strong> 译：定海神针 Pin 和 Unpin</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/sizedness-in-rust/sizedness-in-rust.html"><strong aria-hidden="true">1.12.</strong> Sizedness in Rust</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust生命周期集大成者PhantomData〈T〉/Rust生命周期集大成者PhantomData〈T〉.html"><strong aria-hidden="true">1.13.</strong> Rust生命周期集大成者 PhantomData&lt;T&gt;</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：用Rust做类型体操_Part_0.html"><strong aria-hidden="true">1.14.</strong> 数据库表达式执行的黑魔法：用Rust做类型体操 Part 0</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：GAT实现引用类型关联_Part_1.html"><strong aria-hidden="true">1.15.</strong> 数据库表达式执行的黑魔法：GAT实现引用类型关联 Part 1</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：用HRTB写bound_Part_2.html"><strong aria-hidden="true">1.16.</strong> 数据库表达式执行的黑魔法：用HRTB写bound Part 2</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：用Rust做类型体操之用宏展开重复代码_Part_3_&_4.html"><strong aria-hidden="true">1.17.</strong> 数据库表达式执行的黑魔法：用Rust做类型体操之用宏展开重复代码 Part 3 & 4</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：与Rust编译器斗智斗勇之表达式向量化_Part_5_&_6.html"><strong aria-hidden="true">1.18.</strong> 数据库表达式执行的黑魔法：与Rust编译器斗智斗勇之表达式向量化 Part 5 & 6</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：在Rust中用宏关联逻辑类型和实际类型_Part_7.html"><strong aria-hidden="true">1.19.</strong> 数据库表达式执行的黑魔法：在Rust中用宏关联逻辑类型和实际类型 Part 7</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">2.</strong> 生命周期</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../02_生命周期/Rust中的生命周期——从StrSplit实例说开去/Rust中的生命周期——从StrSplit实例说开去.html"><strong aria-hidden="true">2.1.</strong> Rust中的生命周期——从StrSplit实例说开去</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/与ChatGPT深度对话来学Rust生命周期/与ChatGPT深度对话来学Rust生命周期.html"><strong aria-hidden="true">2.2.</strong> 与ChatGPT深度对话来学Rust生命周期</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/进击的Rust生命周期——early_bound与late_bound（1）/进击的Rust生命周期——early_bound与late_bound（1）.html"><strong aria-hidden="true">2.3.</strong> 进击的Rust生命周期——early_bound与late_bound（1）</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/进击的Rust生命周期——early_bound与late_bound（2）/进击的Rust生命周期——early_bound与late_bound（2）.html"><strong aria-hidden="true">2.4.</strong> 进击的Rust生命周期——early_bound与late_bound（2）</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/进击的Rust生命周期——一力降十会的MIR（1）/进击的Rust生命周期——一力降十会的MIR（1）.html"><strong aria-hidden="true">2.5.</strong> 进击的Rust生命周期——一力降十会的MIR（1）</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/进击的Rust生命周期——一力降十会的MIR（2）/进击的Rust生命周期——一力降十会的MIR（2）.html"><strong aria-hidden="true">2.6.</strong> 进击的Rust生命周期——一力降十会的MIR（2）</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/Common_Rust_Lifetime_Misconceptions/Common_Rust_Lifetime_Misconceptions.html"><strong aria-hidden="true">2.7.</strong> Common Rust Lifetime Misconceptions</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/Rust生命周期常见误区/Rust生命周期常见误区.html"><strong aria-hidden="true">2.8.</strong> 译：Rust生命周期常见误区</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">3.</strong> 无畏并发</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../05_无畏并发/简单写个Rust无锁队列/简单写个Rust无锁队列.html"><strong aria-hidden="true">3.1.</strong> 简单写个Rust无锁队列</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/进击的Rust多线程——混合自旋锁/进击的Rust多线程——混合自旋锁.html"><strong aria-hidden="true">3.2.</strong> 进击的Rust多线程——混合自旋锁</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/An_unsafe_tour_of_Rust's_Send_and_Sync/An_unsafe_tour_of_Rust's_Send_and_Sync.html"><strong aria-hidden="true">3.3.</strong> An unsafe tour of Rust's Send and Sync</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/进击的Rust多线程——Send与Sync/进击的Rust多线程——Send与Sync.html"><strong aria-hidden="true">3.4.</strong> 进击的Rust多线程——Send与Sync</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/进击的Rust多线程——离经叛道的PhantomData/进击的Rust多线程——离经叛道的PhantomData.html"><strong aria-hidden="true">3.5.</strong> 进击的Rust多线程——离经叛道的PhantomData</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/Rust_Async_Pin概念解析/Rust_Async_Pin概念解析.html"><strong aria-hidden="true">3.6.</strong> Rust Async: Pin概念解析</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/Rust和C++的并发库对比/Rust和C++的并发库对比.html"><strong aria-hidden="true">3.7.</strong> 译：Rust 和 C++ 的并发库对比</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/Rust原子类型和内存排序/Rust原子类型和内存排序.html"><strong aria-hidden="true">3.8.</strong> Rust原子类型和内存排序</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">4.</strong> 网络编程</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../06_网络编程/从编解码层面理解WebSocket_手写一个WebSocket/从编解码层面理解WebSocket_手写一个WebSocket.html"><strong aria-hidden="true">4.1.</strong> 从编解码层面理解WebSocket 手写一 个WebSocket</a></li><li class="chapter-item expanded "><a href="../../06_网络编程/透过Rust探索系统的本原：网络篇/透过Rust探索系统的本原：网络篇.html"><strong aria-hidden="true">4.2.</strong> 透过Rust探索系统的本原：网络篇</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">5.</strong> 轮子系列</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../07_轮子系列/700行Rust写一个内存分配器/700行Rust写一个内存分配器.html"><strong aria-hidden="true">5.1.</strong> 700行Rust写一个内存分配器</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/Rust：网络库的实现思路/Rust：网络库的实现思路.html"><strong aria-hidden="true">5.2.</strong> Rust：网络库的实现思路</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/Rust异步运行时基础部件/Rust异步运行时基础部件.html"><strong aria-hidden="true">5.3.</strong> Rust异步运行时基础部件</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/使用Rust+epoll编写异步IO框架/使用Rust+epoll编写异步IO框架（1）.html"><strong aria-hidden="true">5.4.</strong> 使用Rust+epoll编写异步IO框架（1）</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/使用Rust+epoll编写异步IO框架/使用Rust+epoll编写异步IO框架（2）.html"><strong aria-hidden="true">5.5.</strong> 使用Rust+epoll编写异步IO框架（2）</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/使用Rust+epoll编写异步IO框架/使用Rust+epoll编写异步IO框架（3）.html"><strong aria-hidden="true">5.6.</strong> 使用Rust+epoll编写异步IO框架（3）</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day1.html"><strong aria-hidden="true">5.7.</strong> 用rust从零开发一套web框架：day1</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day2.html"><strong aria-hidden="true">5.8.</strong> 用rust从零开发一套web框架：day2</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day3.html"><strong aria-hidden="true">5.9.</strong> 用rust从零开发一套web框架：day3</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day4.html"><strong aria-hidden="true">5.10.</strong> 用rust从零开发一套web框架：day4</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day5.html"><strong aria-hidden="true">5.11.</strong> 用rust从零开发一套web框架：day5</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">6.</strong> 奇技淫巧</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../08_奇技淫巧/Copy-On-Write是不是优化？/Copy-On-Write是不是优化？.html"><strong aria-hidden="true">6.1.</strong> 译：Copy-On-Write是不是优化？</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/揭秘神奇的Rust_Axum风格的函数实现/揭秘神奇的Rust_Axum风格的函数实现.html"><strong aria-hidden="true">6.2.</strong> 译：揭秘神奇的 Rust Axum 风格的函数实现</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/“变长参数”函数与回调/“变长参数”函数与回调.html"><strong aria-hidden="true">6.3.</strong> “变长参数”函数与回调</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/Rust字符串格式化的幕后：format_args!()/Rust字符串格式化的幕后：format_args!().html"><strong aria-hidden="true">6.4.</strong> 译：Rust字符串格式化的幕后：format_args!()</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/给Rust带来一点C++特产/给Rust带来一点C++特产.html"><strong aria-hidden="true">6.5.</strong> 给Rust带来一点C++特产</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/一步步实现_Rust_Bevy_ECS_的_System_简化版本/一步步实现_Rust_Bevy_ECS_的_System_简化版本.html"><strong aria-hidden="true">6.6.</strong> 一步步实现 Rust Bevy ECS 的 System 简化版本</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/Exploring_Design_Patterns_in_Rust_with_Algorithmic_Trading_Examples/Exploring_Design_Patterns_in_Rust_with_Algorithmic_Trading_Examples.html"><strong aria-hidden="true">6.7.</strong> Exploring Design Patterns in Rust with Algorithmic Trading Examples</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">7.</strong> 源码分析</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../09_源码分析/Rust并发：bytes源码分析/Rust并发：bytes源码分析.html"><strong aria-hidden="true">7.1.</strong> Rust并发：bytes源码分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust并发：标准库Arc源码分析/Rust并发：标准库Arc源码分析.html"><strong aria-hidden="true">7.2.</strong> Rust并发：标准库Arc源码分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust并发：标准库sync_Once源码分析/Rust并发：标准库sync_Once源码分析.html"><strong aria-hidden="true">7.3.</strong> Rust并发：标准库sync::Once源码分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust源码阅读：引用计数Rc/Rust源码阅读：引用计数Rc.html"><strong aria-hidden="true">7.4.</strong> Rust源码阅读：引用计数Rc</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust源码阅读：Cell、RefCell与内部可变性/Rust源码阅读：Cell、RefCell与内部可变性.html"><strong aria-hidden="true">7.5.</strong> Rust源码阅读： Cell、RefCell与内部可变性</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/关于_Rust_的_UnsafeCell、Cell_与_RefCell/关于_Rust_的_UnsafeCell、Cell_与_RefCell.html"><strong aria-hidden="true">7.6.</strong> 关于 Rust 的 UnsafeCell、Cell 与 RefCell</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust_Async_async-stream源码分析/Rust_Async_async-stream源码分析.html"><strong aria-hidden="true">7.7.</strong> Rust Async: async-stream源码分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/走进Tokio的异步世界/走进Tokio的异步世界.html"><strong aria-hidden="true">7.8.</strong> 走进 Tokio 的异步世界</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/tokio.rs_runtime的实现/tokio.rs_runtime的实现.html"><strong aria-hidden="true">7.9.</strong> tokio.rs runtime 的实现</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Tokio_internals/Tokio_internals.html"><strong aria-hidden="true">7.10.</strong> Tokio internals</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Tokio_internals/译文：Tokio內部机制.html"><strong aria-hidden="true">7.11.</strong> 译：Tokio 内部机制</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust_Axum_HTTP_框架的架构分析/Rust_Axum_HTTP_框架的架构分析.html"><strong aria-hidden="true">7.12.</strong> Rust Axum HTTP 框架的架构分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/安利一个Rust_Game_Engine：Bevy--ECS部分/安利一个Rust_Game_Engine：Bevy--ECS部分.html"><strong aria-hidden="true">7.13.</strong> 安利一个Rust Game Engine：Bevy--ECS部分</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Tokio_解析之任务调度/Tokio_解析之任务调度.html"><strong aria-hidden="true">7.14.</strong> Tokio 解析之任务调度</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">8.</strong> 生态观察</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../11_生态观察/Rust_web_frameworks_have_subpar_error_reporting/Rust_web_frameworks_have_subpar_error_reporting.html"><strong aria-hidden="true">8.1.</strong> Rust web frameworks have subpar error reporting</a></li><li class="chapter-item expanded "><a href="../../11_生态观察/SeaORM：要做Rust版本的ActiveRecord/SeaORM：要做Rust版本的ActiveRecord.html"><strong aria-hidden="true">8.2.</strong> SeaORM：要做Rust版本的ActiveRecord</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">9.</strong> 死灵终极</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_总述.html"><strong aria-hidden="true">9.1.</strong> 译：Learn Rust the Dangerous Way 总述</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_0.html"><strong aria-hidden="true">9.2.</strong> 译：Learn Rust the Dangerous Way 0</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_1.html"><strong aria-hidden="true">9.3.</strong> 译：Learn Rust the Dangerous Way 1</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_2.html"><strong aria-hidden="true">9.4.</strong> 译：Learn Rust the Dangerous Way 2</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_3.html"><strong aria-hidden="true">9.5.</strong> 译：Learn Rust the Dangerous Way 3</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_4.html"><strong aria-hidden="true">9.6.</strong> 译：Learn Rust the Dangerous Way 4</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_5.html"><strong aria-hidden="true">9.7.</strong> 译：Learn Rust the Dangerous Way 5</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Unsafe_Rust_随堂小测/Unsafe_Rust_随堂小测（一）.html"><strong aria-hidden="true">9.8.</strong> Unsafe Rust 随堂小测（一）</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Unsafe_Rust_随堂小测/Unsafe_Rust_随堂小测（二）.html"><strong aria-hidden="true">9.9.</strong> Unsafe Rust 随堂小测（二）</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Unsafe_Rust_随堂小测/Unsafe_Rust_随堂小测（三）.html"><strong aria-hidden="true">9.10.</strong> Unsafe Rust 随堂小测（三）</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Unsafe_Rust_随堂小测/Unsafe_Rust_随堂小测参考答案.html"><strong aria-hidden="true">9.11.</strong> Unsafe Rust 随堂小测参考答案</a></li></ol></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky bordered">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">Rust 优秀博文</h1>

                    <div class="right-buttons">
                        <a href="../../print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script type="text/javascript">
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="关于rust中trait二"><a class="header" href="#关于rust中trait二">关于rust中trait(二)</a></h1>
<p>作者：<a href="https://www.jianshu.com/u/f5f514c417e6">神奇的考拉</a></p>
<p>原载：<a href="https://www.jianshu.com/p/4a63d2b74da4">https://www.jianshu.com/p/4a63d2b74da4</a></p>
<p>在Rust中默认定义了一些比较常用的trait，主要是为了满足不同的场景下使用。但其中一些trait(Deref/AsRef/Borrow/Cow)的概念理解起来有点“晦涩”；
对于初学 Rust 的新手，对这几个概念会十分迷惑。所以，现在就让我们一起来探索一下。</p>
<h2 id="一按模块分类理解"><a class="header" href="#一按模块分类理解">一、<strong>按模块分类理解</strong></a></h2>
<p>其实按标准库的分类，首先就可以略知一二它们的作用。</p>
<ol>
<li><strong>std::ops::Deref</strong> ：Deref 是被归类为 ops 模块。这个模块下放的都是可重载的操作符。这些操作符都有对应的 <strong>trait</strong>：比如<code>Add trait</code> 对应的就是 <code>+</code>；
而 <code>Deref trait</code> 则对应<em>共享(不可变)借用 的解引用</em>操作，比如 <code>*v</code>; 相应的，也有 <code>DerefMut trait</code>，对应<em>独占(可变)借用的解引用</em>操作。由于 Rust 所有权语义是贯穿整个语言特性，所以 <code>拥有（Owner）</code>/<code>不可变借用（&amp;T）</code>/<code>可变借用（&amp;mut T)</code>的语义都是配套出现的。</li>
<li><strong>std::convert::AsRef</strong> ：AsRef 被归类到 convert 模块。这个模块下放的都是拥有类型转换的 <strong>trait</strong> 。比如熟悉的 <code>From/Into</code> 、<code>TryFrom/TryInto</code> ，而 <code>AsRef/AsMut</code>也是作为配对出现在这里，<strong><code>说明该trait 是和类型转化有关</code></strong>。再根据 <strong>Rust API Guidelines</strong> 里的命名规范可以推理，以 <code>as_</code> 开头的方法，代表从 <code>borrowed -&gt; borrowed</code> ，即 <code>reference -&gt; reference</code>的一种转换，并且是无开销的。并且这种转换不能失败。</li>
<li><strong>std::borrow::Borrow</strong>:  Borrow 被归类到 borrow 模块中。而该模块的文档则相对比较简陋：<em>这是用于使用借来的数据</em>。所以该 trait 多多少少和表达借用语义是相关的。提供了三个 <strong>trait</strong> : <strong>Borrow</strong> / <strong>BorrowMut</strong>/ <strong>ToOwned</strong> ，可以说是和所有权语义完全对应了。</li>
<li><strong>std::borrow::Cow</strong>： Cow 也被归类为 borrow 模块中。根据描述，Cow 是 一种 clone-on-write 的智能指针。被放到 borrow 模块，主要还是为了尽可能的使用 借用 而避免 拷贝，是一种优化。</li>
</ol>
<h2 id="二trait详解"><a class="header" href="#二trait详解">二、trait详解</a></h2>
<p>接下来逐个深入了解</p>
<h4 id="stdopsderef"><a class="header" href="#stdopsderef"><strong>std::ops::Deref</strong></a></h4>
<p>1、定义：</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>pub trait Deref {
    type Target: ?Sized;
    #[must_use]
    pub fn deref(&amp;self) -&gt; &amp;Self::Target;
}
<span class="boring">}
</span></code></pre></pre>
<p>其实定义不复杂，Deref 只包含一个 <code>deref</code> 方法签名。该 trait 妙就妙在，它会被编译器 「隐式」调用，官方的说法叫 <strong>deref. 强转（deref coercion）</strong> 。标准库示例：</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>use std::ops::Deref;

struct DerefExample&lt;T&gt; {
    value: T,    // Value类型为T(泛型)
}
// 实现Deref特型trait
// 内部可操作类型：T；与结构体DerefExample中字段value相同
impl&lt;T&gt; Deref for DerefExample&lt;T&gt; {
    type Target = T;

   // 接收一个DerefExample的引用; 输出DerefExample的内部字段的引用
    fn deref(&amp;self) -&gt; &amp;Self::Target {
        &amp;self.value
    }
}

// 验证
// x类型：DerefExample&lt;char&gt;
// 此时DerefExample中的T=char
let x = DerefExample { value: 'a' };

// 此时*x解引用会调用deref方法，进行引用转换输出field: value的内容
// *x等同于*Deref::deref(&amp;x)
assert_eq!('a', *x);
<span class="boring">}
</span></code></pre></pre>
<p>代码中，DerefExample 结构体实现了 Deref trait，那么它就能被使用 解引用操作符<code>*</code> 来执行了。示例中，直接返回字段 value 的值。</p>
<p>可以看得出来：<code>DerefExample 实现了 Deref 而拥有了一种类似于 指针的行为，因为它可以被解引用了。所以为了方便理解这种行为，我们称之为「指针语义」。DerefExample 也就变成了一种智能指针。这也是识别一个类型是否为智能指针的方法之一，看它是否实现 Deref</code>。但并不是所有智能指针都要实现 Deref ，也有的是实现 Drop ，或同时实现。</p>
<p>现在让我们来总结 Deref。
如果 <code>T</code>实现了 <code>Deref&lt;Target = U&gt;</code>，并且 <code>x</code>是 类型 <code>T</code>的一个实例，那么：</p>
<ol>
<li>在不可变的上下文中，<code>*x</code> （此时 <code>T</code> 既不是引用也不是原始指针）操作等价于 <code>*Deref::deref(&amp;x)</code>。</li>
<li><code>&amp;T</code> 的值会强制转换为 <code>&amp;U</code> 的值。</li>
<li>相当于 <code>T</code> 实现了 <code>U</code> 的所有（不可变）方法。</li>
</ol>
<p>Deref 的妙用在于提升了 Rust 的开发体验。标准库里典型的示例就是 <code>Vec&lt;T&gt;</code> 通过实现 <code>Deref</code> 而共享了 <code>slice</code>的所有方法。</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>impl&lt;T, A: Allocator&gt; ops::Deref for Vec&lt;T, A&gt; {
    type Target = [T];

    fn deref(&amp;self) -&gt; &amp;[T] {
        unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } // 此处开销并不大
    }
}
<span class="boring">}
</span></code></pre></pre>
<p>比如， <code>len()</code> 方法实际上是在 <strong><code>slice</code> 模块</strong>被定义的。但因为 在 Rust 里，当执行 <code>.</code>调用，或在函数参数位置，都会被*<code>编译器自动执行 deref 强转这种隐式行为</code>*，所以，就相当于 <code>Vec&lt;T&gt;</code> 也拥有了 <code>slice</code>的方法。
如下样例：</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
 let a = vec![1, 2, 3];
 assert_eq!(a.len(), 3); // 当 a 调用 len() 的时候，发生 deref 强转
}
</code></pre></pre>
<p>在Rust 中的隐式行为并不多见，但是 Deref 这种隐式强转的行为，为我们方便使用智能指针提供了便利。</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
    let h = Box::new(&quot;hello&quot;);
    assert_eq!(h.to_uppercase(), &quot;HELLO&quot;);
}
</code></pre></pre>
<p>比如我们操作 <code>Box&lt;T&gt;</code>，我们就不需要手动解引用取出里面<code>T</code>来操作，而是当 <code>Box&lt;T&gt;</code> 外面这一层是透明的，直接来操作 T 就可以了。</p>
<p>再比如：</p>
<pre><pre class="playground"><code class="language-rust">fn uppercase(s: &amp;str) -&gt; String {
    s.to_uppercase()
}

fn main() {
    let s = String::from(&quot;hello&quot;);
    assert_eq!(uppercase(&amp;s), &quot;HELLO&quot;);
}
</code></pre></pre>
<p>上面 uppercase 方法的参数类型 明明是 <code>&amp;str</code>，但现在main函数中实际传的类型是 <code>&amp;String</code>，为什么编译可以成功呢？就是因为 String 实现了 Deref :</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>impl ops::Deref for String {
    type Target = str;

    #[inline]
    fn deref(&amp;self) -&gt; &amp;str {
        unsafe { str::from_utf8_unchecked(&amp;self.vec) }
    }
}
<span class="boring">}
</span></code></pre></pre>
<p>这就是 Deref 的妙用。但是有些人可能会“恍然大悟”，这不就是继承吗？大误。
这种行为好像有点像继承，但请不要随便用 Deref 来模拟继承。</p>
<h4 id="stdconvertasref"><a class="header" href="#stdconvertasref"><strong>std::convert::AsRef</strong></a></h4>
<p>来看一下 AsRef 的定义：</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>pub trait AsRef&lt;T: ?Sized&gt; {
    fn as_ref(&amp;self) -&gt; &amp;T;
}
<span class="boring">}
</span></code></pre></pre>
<p>我们已经知道 AsRef 可以用于转换。相比较于拥有隐式行为的 Deref ，<em><code>AsRef 属于显式的转换</code></em>。</p>
<pre><pre class="playground"><code class="language-rust">fn is_hello&lt;T: AsRef&lt;str&gt;&gt;(s: T) {
   assert_eq!(&quot;hello&quot;, s.as_ref());
}

fn main() {
    let s = &quot;hello&quot;;
    is_hello(s);

    let s = &quot;hello&quot;.to_string();
    is_hello(s);
}
</code></pre></pre>
<p>上面示例中，is_hello 的函数是泛型函数。通过 <code>T: AsRef&lt;str&gt;</code>的限定，并且在函数内使用 <code>s.as_ref()</code>这样的显式调用来达到转换的效果。不管是 <code>String</code> 还是 <code>str</code>其实都实现了 <code>AsRef</code> trait。</p>
<p>那现在问题来了，什么时候使用 <code>AsRef</code> 呢？为啥不直接用 <code>&amp;T</code> ？</p>
<p>举一个示例：</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>// 定义struct
pub struct Thing {
    name: String,
}
// 实现
impl Thing {
    pub fn new(name: WhatTypeHere) -&gt; Self {
        Thing { name: name.some_conversion() }
}
<span class="boring">}
</span></code></pre></pre>
<p>上面示例中，new函数 name的类型参数有以下几种情况选择：</p>
<ol>
<li><code>&amp;str</code>。此时， 调用方（caller）需要传入一个引用。但是为了转换为 String ，则被调方（callee）则需要自己控制内存分配，并且会有拷贝。</li>
<li><code>String</code>。此时，调用方传 String 还好，如果是传引用，则和情况 1 相似。</li>
<li><code>T: Into&lt;String&gt;</code>。此时，调用方可以传 <code>&amp;str</code> 和<code>String</code>，但是在类型转换的时候同样会有内存分配和拷贝的情况。</li>
<li><code>T: AsRef&lt;str&gt;</code>。同 情况 3 。</li>
<li><code>T: Into&lt;Cow&lt;'a, str&gt;&gt;</code>，此时，可以避免一些分配。后面会介绍 <code>Cow</code>。</li>
</ol>
<p>到底何时使用哪种类型，这个其实没有一个标准答案。有的人就是喜欢 <code>&amp;str</code> ，不管在什么地方都会使用它。这里面其实是需要权衡的：</p>
<ol>
<li>有些分配和拷贝是无关紧要的，所以就没有必要让类型签名过度复杂化，直接使用 <code>&amp;str</code>就可以了。</li>
<li>有些是需要看方法定义，是否需要消耗所有权，或者返回所有权还是借用。</li>
<li>有些则是需要尽量减少分配和拷贝，那就必须使用比较复杂的类型签名，比如情况5。</li>
</ol>
<p>通过显式调用 <code>.as_ref()</code>，就可以得到父类结构的引用。
Deref 注重隐式透明地使用 父类结构，而 AsRef 则注重显式地获取父类结构的引用。这是结合具体的 API 设计所作的权衡，而不是无脑模拟 OOP 继承。</p>
<h4 id="stdborrowborrow"><a class="header" href="#stdborrowborrow"><strong>std::borrow::Borrow</strong></a></h4>
<p>来看一下 Borrow 的定义：</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>pub trait Borrow&lt;Borrowed: ?Sized&gt; {
    fn borrow(&amp;self) -&gt; &amp;Borrowed;
}
<span class="boring">}
</span></code></pre></pre>
<p>对比一下 AsRef:</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>pub trait AsRef&lt;T: ?Sized&gt; {
    fn as_ref(&amp;self) -&gt; &amp;T;
}
<span class="boring">}
</span></code></pre></pre>
<p>是不是非常相似？所以，有人提出，这俩 trait 完全可以去掉一个。但实际上，Borrow 和 AsRef 是有区别的，它们都有存在的意义。</p>
<p>Borrow trait是用来表示 借用数据。而 AsRef 则是用来表示类型转换。在Rust中，为不同的语义不同的使用情况提供不同的类型表示是很常见的。</p>
<p>一个类型通过实现 Borrow，在 <code>borrow()</code>方法中提供对 <code>T</code> 的引用/借用，表达的语义是可以作为某个类型 <code>T</code>被借用，而非转换。一个类型可以自由地借用为几个不同的类型，也可以用可变的方式借用。</p>
<p>所以 Borrow 和 AsRef 如何选呢？</p>
<ul>
<li>当你想把不同类型的借用进行统一抽象，或者当你要建立一个数据结构，以同等方式处理自拥有值（ownered）和借用值（borrowed）时，例如散列（hash）和比较（compare）时，选择Borrow。</li>
<li>当你想把某个类型直接转换为引用，并且你正在编写通用代码时，选择AsRef。比较简单的情况。</li>
</ul>
<p>其实在标准库文档中给出的 HashMap 示例已经说明的很好了：
<code>HashMap&lt;K, V&gt;</code> 存储键值对，对于 API 来说，无论使用 Key 的自有值，还是其引用，应该都可以正常地在 HashMap 中检索到对应的值。因为 HashMap 要对 key 进行 hash计算 和 比较，所以必须要求 不管是 Key 的自有值，还是引用，在进行 hash计算和比较的时候，行为应该是一致的。</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>use std::borrow::Borrow;
use std::hash::Hash;

pub struct HashMap&lt;K, V&gt; {
    // fields omitted
}

impl&lt;K, V&gt; HashMap&lt;K, V&gt; {
    // insert 方法使用 Key 的自有值，拥有所有权
    pub fn insert(&amp;self, key: K, value: V) -&gt; Option&lt;V&gt;
    where K: Hash + Eq
    {
        // ...
    }

    // 使用 get 方法通过 key 来获取对应的值，则可以使用 key的引用，这里用 &amp;Q 表示
    // 并且要求 Q 要满足 `Q: Hash + Eq + ?Sized `
    // 而 K 呢 ，通过 `K: Borrow&lt;Q&gt;` 来表达 K 是 Q 的一个借用数据。
    // 所以，这里要求 Q 的 hash 实现 和 K 是一样的，否则编译就会出错
    pub fn get&lt;Q&gt;(&amp;self, k: &amp;Q) -&gt; Option&lt;&amp;V&gt;
    where
        K: Borrow&lt;Q&gt;,
        Q: Hash + Eq + ?Sized
    {
        // ...
    }
}
<span class="boring">}
</span></code></pre></pre>
<p>代码的注释基本已经说明了问题。Borrow 是对借用数据的一种限制，并且配合额外的trait来使用，比如示例中的 <code>Hash</code> 和 <code>Eq</code> 等。</p>
<p>再看一个示例：</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>// 这个结构体能不能作为 HashMap 的 key？
pub struct CaseInsensitiveString(String);

// 它实现 Eq 没有问题
impl  PartialEq for CaseInsensitiveString {
    fn eq(&amp;self, other: &amp;Self) -&gt; bool {
       // 但这里比较是要求忽略了 ascii 大小写
        self.0.eq_ignore_ascii_case(&amp;other.0)
    }
}

impl Eq for CaseInsensitiveString { }

// 实现 Hash 没有问题
// 但因为 eq 忽略大小写，那么 hash 计算也必须忽略大小写
impl Hash for CaseInsensitiveString {
    fn hash&lt;H: Hasher&gt;(&amp;self, state: &amp;mut H) {
        for c in self.0.as_bytes() {
            c.to_ascii_lowercase().hash(state)
        }
    }
}
<span class="boring">}
</span></code></pre></pre>
<p>但是 CaseInsensitiveString 可以实现 <code>Borrow&lt;str&gt;</code>吗？</p>
<p>很显然，CaseInsensitiveString 和 str 对 Hash 的实现不同，str 是不会忽略大小写的。因此，CaseInsensitiveString 不能实现 <code>Borrow&lt;str&gt;</code>，所以 CaseInsensitiveString 不能作为 HashMap 的 key，但编译器无法通过 Borrow trait 来识别这种情况。</p>
<p>但是 CaseInsensitiveString 完全可以实现 AsRef 。</p>
<p>这就是 Borrow 和 AsRef 的区别，Borrow 更加严格一些，并且表示的语义和 AsRef 完全不同。</p>
<h4 id="stdborrowcow"><a class="header" href="#stdborrowcow"><strong>std::borrow::Cow</strong></a></h4>
<p>看一下 Cow 的定义：</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>pub enum Cow&lt;'a, B&gt; 
where  B: 'a + ToOwned + ?Sized, 
 {
    Borrowed(&amp;'a B),
    Owned(&lt;B as ToOwned&gt;::Owned),
}
<span class="boring">}
</span></code></pre></pre>
<p>看得出来， Cow 是一个枚举。有点类似于 Option，表示两种情况中的某一种。Cow 在这里就是表示 借用的 和 自有的，但只能出现其中的一种情况。</p>
<p>Cow 主要功能：</p>
<ol>
<li>作为智能指针，提供对此类型实例的透明的不可变访问（比如可直接调用此类型原有的不可变方法，实现了Deref ，但没实现 DerefMut）；</li>
<li>如果遇到需要修改此类型实例，或者需要获得此类型实例的所有权的情况，<code>Cow</code> 提供方法做克隆（Clone）处理，并避免多次重复克隆。</li>
</ol>
<p><code>Cow</code> 的设计目的是提高性能（减少复制）同时增加灵活性，因为大部分情况下，业务场景都是读多写少。利用 <code>Cow</code>，可以用统一，规范的形式实现，需要写的时候才做一次对象复制。这样就可能会大大减少复制的次数。</p>
<p>它有以下几个要点需要掌握：</p>
<ol>
<li>
<p><code>Cow&lt;T&gt;</code> 能直接调用 <code>T</code> 的不可变方法，因为 <code>Cow</code> 这个枚举，实现了 <code>Deref</code>；</p>
</li>
<li>
<p>在需要修改</p>
<pre><code>T
</code></pre>
<p>的时候，可以使用</p>
<pre><code>.to_mut()
</code></pre>
<p>方法得到一个具有所有权的值的可变借用；</p>
<ul>
<li>
<ol>
<li>注意，调用 <code>.to_mut()</code> 不一定会产生Clone；</li>
</ol>
</li>
<li>
<ol>
<li>在已经具有所有权的情况下，调用 <code>.to_mut()</code> 有效，但是不会产生新的Clone；</li>
</ol>
</li>
<li>
<ol>
<li>多次调用 <code>.to_mut()</code> 只会产生一次Clone。</li>
</ol>
</li>
</ul>
</li>
<li>
<p>在需要修改</p>
<pre><code>T
</code></pre>
<p>的时候，可以使用</p>
<pre><code>.into_owned()
</code></pre>
<p>创建新的拥有所有权的对象，这个过程往往意味着内存拷贝并创建新对象；</p>
<ul>
<li>
<ol>
<li>如果之前 <code>Cow</code> 中的值是借用状态，调用此操作将执行Clone；</li>
</ol>
</li>
<li>
<ol>
<li>本方法，参数是<code>self</code>类型，它会“消费”原先的那个类型实例，调用之后原先的类型实例的生命周期就截止了，在 <code>Cow</code> 上不能调用多次；</li>
</ol>
</li>
</ul>
</li>
</ol>
<p>Cow 在 API 设计上用的比较多：</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>use std::borrow::Cow;

// 返回值使用 Cow ，避免多次拷贝
fn remove_spaces&lt;'a&gt;(input: &amp;'a str) -&gt; Cow&lt;'a, str&gt; {
    if input.contains(' ') {
        let mut buf = String::with_capacity(input.len());
        for c in input.chars() {
            if c != ' ' {
                buf.push(c);
            }
        }
        return Cow::Owned(buf);
    }
    return Cow::Borrowed(input);
}
<span class="boring">}
</span></code></pre></pre>
<p>当然，什么时候使用 Cow ，又回到了我们前文中那个「什么时候使用 <code>AsRef</code> 」的讨论，一切都要权衡，并没有放之四海皆准的标准答案。</p>
<h2 id="三引用"><a class="header" href="#三引用">三、引用</a></h2>
<p><a href="https://links.jianshu.com/go?to=https%3A%2F%2Fdoc.rust-lang.org%2Fstd%2Fops%2Ftrait.Deref.html">关于Deref</a>
<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fdoc.rust-lang.org%2Fstd%2Fops%2Ftrait.Deref.html%23more-on-deref-coercion">deref. 强转(deref coercion)</a>
<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fdoc.rust-lang.org%2Fstd%2Fconvert%2Ftrait.AsRef.html">关于AsRef</a>
<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fdoc.rust-lang.org%2Fstd%2Fborrow%2Ftrait.Borrow.html">关于Borrow</a>
<a href="https://links.jianshu.com/go?to=https%3A%2F%2Fdoc.rust-lang.org%2Fstd%2Fborrow%2Fenum.Cow.html">关于Cow</a></p>
<p>作者：神奇的考拉</p>
<p>链接：<a href="https://www.jianshu.com/p/4a63d2b74da4">https://www.jianshu.com/p/4a63d2b74da4</a></p>
<p>来源：简书</p>
<p>著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                            <a rel="prev" href="../../01_类型系统/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>

                            <a rel="next" href="../../01_类型系统/Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然/Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                    <a rel="prev" href="../../01_类型系统/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>

                    <a rel="next" href="../../01_类型系统/Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然/Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>




        <script type="text/javascript">
            window.playground_copyable = true;
        </script>


        <script src="../../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../mark.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../searcher.js" type="text/javascript" charset="utf-8"></script>

        <script src="../../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../highlight.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../book.js" type="text/javascript" charset="utf-8"></script>

        <!-- Custom JS scripts -->


    </body>
</html>
